package com.example.synchronizedLearning;

public class Syn3 {
    /**
     * synchronized 修饰静态方法时，锁住的是类对象（Class），而不是实例对象。
     * 所有实例共享类锁，因此不同对象之间也会相互阻塞。
     * <p>
     * synchronized 修饰的静态方法会锁住当前类的类对象（Class对象），而不是某个实例对象。
     * 在 JVM 运行时，每个类在方法区（Method Area）中都有一个对应的 Class 对象。
     * Class 对象是类的元信息（metadata），包括类名、方法、字段等。
     * 当一个线程访问 synchronized static 方法时，线程需要先获取该类对象的锁（即 Class对象 的锁），在锁未释放之前，其他线程即使是针对不同对象的调用，也会被阻塞。
     */
    public synchronized static void print() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + "-" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

/**
 * 在 JVM 中，每个加载的类在方法区（Method Area）中只有唯一的 Class 对象。
 * Class 对象由 JVM 自动创建，保存了类的结构信息（字段、方法、继承关系等）。
 * Class 对象可以通过以下方式获取：
 * ClassName.class
 * Class.forName("ClassName")
 * object.getClass()
 */
class Syn3Test {
    public static void main(String[] args) {

        /**
         * 同一个类
         */
        Thread t1 = new Thread(() -> Syn3.print());
        Thread t2 = new Thread(() -> Syn3.print());

        t1.setName("t1");
        t2.setName("t2");

        System.out.println(t1.getName() + " : " + t1.getState());
        System.out.println(t2.getName() + " : " + t2.getState());

        /**
         * synchronized static 修饰 print() 方法，锁住的是 Syn3.class 对象。
         * t1 首先获取到 Syn3.class 的锁，开始执行。
         * t2 在 t1 完成执行之前，必须等待，进入 BLOCKED 状态。
         * t1 完成后，释放 Syn3.class 的锁，t2 才能继续执行。
         */

        t1.start();
        t2.start();

        System.out.println(t1.getName() + " : " + t1.getState());
        System.out.println(t2.getName() + " : " + t2.getState());

    }
}
